package com.edushare.common.dao.academics.grades;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.query.SelectQuery;

import com.edushare.common.dao.CayenneBasedDAO;
import com.edushare.common.dao.CoursesDAO;
import com.edushare.common.dao.DepartmentsDAO;
import com.edushare.common.orm.ORMInterface;
import com.edushare.common.vo.CourseInstances;
import com.edushare.common.vo.Departments;
import com.edushare.common.vo.GradeKey;
import com.edushare.common.vo.Universities;

public class EntityLetterGrade extends CayenneBasedDAO {
	public EntityLetterGrade(ORMInterface ormInterface) {
		super(ormInterface);
	}

	public List<GradeKey> getDeptGrades(Departments dept) {
		List<GradeKey> gkList = getActiveKeys(dept.getDepartmentId(),
				GradeKey.DEPARTMENT_KEY);
		if(gkList.size() == 0){
			Universities univ = new DepartmentsDAO(ormInterface).getParent(dept);
			UnivLetterGrades ulg = new UnivLetterGrades(ormInterface);
			if(ulg.hasLetterGrades(univ)){
				copyDeptGrade(dept);
				gkList = getActiveKeys(dept.getDepartmentId(),
						GradeKey.DEPARTMENT_KEY);
			}
		}
		Collections.sort(gkList);
		return gkList;
	}

	public List<GradeKey> getCourseGrades(CourseInstances course) {
		List<GradeKey> gkList = getActiveKeys(course.getCourseInstanceId(),
				GradeKey.COURSE_KEY);
		if(gkList.size() == 0){
			Departments dept = new CoursesDAO(ormInterface).getParentDept(course.getCourse());
			if(deptHasGrades(dept)){
				copyCourseGrade(course);
				gkList = getActiveKeys(course.getCourseInstanceId(), GradeKey.COURSE_KEY);
			}
		}
		Collections.sort(gkList);
		return gkList;
	}

	public boolean deptHasGrades(Departments dept) {
		return getDeptGrades(dept).size() >0;
	}

	public boolean courseHasGrade(CourseInstances course) {
		return getCourseGrades(course).size()>0;
	}

	public void copyDeptGrade(Departments dept) {
		Universities univ = new DepartmentsDAO(ormInterface).getParent(dept);
		UnivLetterGrades ugl = new UnivLetterGrades(ormInterface);
		if(!ugl.hasLetterGrades(univ))
			return;
		List<GradeKey> ugkList = ugl.getSetOfGrades(univ, ugl.getActiveVersion(univ));
		copyKeySet(dept.getDepartmentId(), GradeKey.DEPARTMENT_KEY, ugkList);
	}

	public void copyCourseGrade(CourseInstances course) {
		Departments dept = new CoursesDAO(ormInterface).getParentDept(course
				.getCourse());
		if (!deptHasGrades(dept)) {
			return;
		}
		List<GradeKey> parentKeys = getDeptGrades(dept);
		copyKeySet(course.getCourseInstanceId(), GradeKey.COURSE_KEY, parentKeys);
	}

	public void editGrade(GradeKey key, double max, double min) {
		key.setMaximumMarks(max);
		key.setMinimumMarks(min);
		getDataContext().commitChanges();
	}

	@SuppressWarnings("unchecked")
	public List<GradeKey> getActiveKeys(int entityId, int entityType) {
		Expression exp = Expression
				.fromString("entityId = $entityId and entityType = $entityType and active = $active");
		HashMap<String, Integer> map = new HashMap<String, Integer>();
		map.put("entityId", entityId);
		map.put("entityType", entityType);
		map.put("active", GradeKey.ACTIVE_KEY);
		SelectQuery q = new SelectQuery(GradeKey.class, exp
				.expWithParameters(map));
		return getDataContext().performQuery(q);
	}
	
	private void copyKeySet(int entityId, int entityType, List<GradeKey> parentList){
		for(GradeKey gk:parentList){
			GradeKey newK = new GradeKey();
			newK.setActive(GradeKey.ACTIVE_KEY);
			newK.setEntityId(entityId);
			newK.setEntityType(entityType);
			newK.setGradeAlphabet(gk.getGradeAlphabet());
			newK.setGradeNumber(gk.getGradeNumber());
			newK.setKeyVersion(gk.getKeyVersion());
			newK.setMaximumMarks(gk.getMaximumMarks());
			newK.setMinimumMarks(gk.getMinimumMarks());
			newK.setParent(gk);
			newK.setPass(gk.isPass());
			getDataContext().registerNewObject(newK);
		}
		getDataContext().commitChanges();
	}
}
